/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.gr.staffpm.security.dao;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.gr.staffpm.dao.HibernateDao;
import com.gr.staffpm.datatypes.Group;
import com.gr.staffpm.datatypes.Role;
import com.gr.staffpm.datatypes.User;
import com.gr.staffpm.security.constants.StaffPMRoles;

@Repository("userDAO")
@SuppressWarnings("unchecked")
public class HibernateUserDAO extends HibernateDao implements UserDAO {

    @Override
    public User getUser(int userId) {
        return (User) getSession().get(User.class, userId);
    }

    @Override
    public User findUser(String username) {
        Criteria crit = getSession().createCriteria(User.class);
        crit.add(Restrictions.eq(User.USERNAME, username));
        return (User) crit.uniqueResult();
    }

    @Override
    public void createUser(User user) {
        getSession().save(user);
    }

    @Override
    public List<User> getAllUsers() {
        Criteria crit = getSession().createCriteria(User.class);
        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return crit.list();
    }

    @Override
    public void deleteUser(int userId) {
        User user = getUser(userId);
        if (user != null) {
            getSession().delete(user);
        }
    }

    @Override
    public void addOrUpdateUser(User user) {
        getSession().saveOrUpdate(user);
    }

    @Override
    public List<User> getAllUsers(String property, boolean ascending) {
        Criteria crit = getSession().createCriteria(User.class);
        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        Order order;

        if (property == null) {
            if (ascending)
                order = Order.asc(User.USERNAME);
            else
                order = Order.desc(User.USERNAME);
        } else if (property == User.FULL_NAME) {
            if (ascending) {
                crit.addOrder(Order.asc(User.LAST_NAME));
                order = Order.asc(User.FIRST_NAME);
            } else {
                crit.addOrder(Order.desc(User.LAST_NAME));
                order = Order.desc(User.FIRST_NAME);
            }
        } else {
            if (ascending)
                order = Order.asc(property);
            else
                order = Order.desc(property);
        }

        crit.addOrder(order);
        return crit.list();
    }

    /* (non-Javadoc)
     * @see com.gr.staffpm.security.dao.UserDAO#getUsersInGroupByGroupName(java.lang.String)
     */
    @Override
    public List<User> getUsersInGroupByGroupName(String groupName) {
        Criteria crit = getSession().createCriteria(Group.class);
        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        crit.add(Restrictions.eq(Group.NAME, groupName));
        Group group = (Group) crit.uniqueResult();
        List<User> users = new ArrayList<User>(group.getUsers());
        return users;
    }

    /* (non-Javadoc)
     * @see com.gr.staffpm.security.dao.UserDAO#getUserRole()
     */
    @Override
    public Role getUserRole() {
        Criteria crit = getSession().createCriteria(Role.class);
        crit.add(Restrictions.eq(Role.ROLE, StaffPMRoles.USER));
        return (Role) crit.uniqueResult();
    }

    /* (non-Javadoc)
     * @see com.gr.staffpm.security.dao.UserDAO#addRole(com.gr.staffpm.datatypes.User, java.lang.String)
     */
    @Override
    public void addRole(User user, String roleName) {
        Criteria crit = getSession().createCriteria(Role.class);
        crit.add(Restrictions.eq(Role.ROLE, roleName));
        Role role = (Role) crit.uniqueResult();
        user.getRoles().add(role);
        getSession().saveOrUpdate(user);
    }

    /* (non-Javadoc)
     * @see com.gr.staffpm.security.dao.UserDAO#getAllRoles()
     */
    @Override
    public List<Role> getAllRoles() {
        Criteria crit = getSession().createCriteria(Role.class);
        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return crit.list();
    }

    /* (non-Javadoc)
     * @see com.gr.staffpm.security.dao.UserDAO#addRoles(com.gr.staffpm.datatypes.User, java.util.List)
     */
    @Override
    public void addRoles(User user, List<Role> roles) {
        user.getRoles().addAll(roles);
        getSession().saveOrUpdate(user);
    }

    /* (non-Javadoc)
     * @see com.gr.staffpm.security.dao.UserDAO#getAllGroups()
     */
    @Override
    public List<Group> getAllGroups() {
        Criteria crit = getSession().createCriteria(Group.class);
        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return crit.list();
    }

}
